:sparkles feat(day-view): show preview for new events#1371
:sparkles feat(day-view): show preview for new events#1371victor-enogwe merged 5 commits intomainfrom
Conversation
- Added `useOpenAgendaEventPreview` and `useOpenEventContextMenu` hooks to manage event previews and context menus. - Created tests for both hooks to ensure correct functionality when interacting with events. - Refactored event form handling in `useOpenEventForm` to streamline event creation and editing. - Introduced `useCloseEventForm` hook to handle closing event forms and resetting drafts. - Updated `useSaveEventForm` to integrate with the new close event form logic. - Enhanced utility functions for event handling and focus management. - Removed unnecessary context providers from `DayViewContent` for cleaner component structure. - add a re-resizable package
There was a problem hiding this comment.
Pull request overview
This PR refactors the event form handling system to support previewing new events before they are saved. The changes migrate from a React Context-based approach to a more lightweight RxJS BehaviorSubject pattern for state management, eliminating unnecessary context providers and improving performance.
Key Changes:
- Introduced event preview functionality that displays draft events on the calendar surface
- Refactored state management using RxJS BehaviorSubjects instead of React Context
- Added
re-resizablepackage for future event resizing functionality (currently disabled)
Reviewed changes
Copilot reviewed 51 out of 52 changed files in this pull request and generated 14 comments.
Show a summary per file
| File | Description |
|---|---|
| yarn.lock, packages/web/package.json | Added re-resizable package dependency |
| useSaveEventForm.ts | Refactored to dynamically determine if event exists using store selector |
| useOpenEventForm.ts | Major refactor to support draft event previews with scroll handling |
| useCloseEventForm.ts | New hook to centralize event form closing logic |
| useOpenAgendaEventPreview.ts, useOpenEventContextMenu.ts | Simplified to use new state management approach |
| useAgendaInteractionsAtCursor.ts | New hook to configure floating-ui interactions |
| useDraft.ts | New hook using BehaviorSubject for draft state management |
| useOpenAtCursor.ts | Converted from context to standalone hook with RxJS observables |
| useFloatingAtCursor.ts | New hook to manage floating UI positioning |
| useGridMaxZIndex.ts | New hook for reactive z-index management |
| DraftProviderV2.tsx, useDraftContextV2.ts, open-at-cursor.tsx | Removed context providers |
| DayViewContent.tsx | Removed unnecessary context providers, cleaner structure |
| Agenda.tsx | Integrated new hooks and manages floating UI instances |
| NowLine.tsx | Refactored to use event emitter for scroll-to-now functionality |
| TimedAgendaEvents.tsx, AllDayAgendaEvents.tsx | Added draft event rendering and interactions support |
| DraggableTimedAgendaEvent.tsx, DraggableAllDayAgendaEvent.tsx | Added Resizable wrapper and interaction handlers |
| EventContextMenu.tsx, AgendaEventPreview.tsx, FloatingEventForm.tsx | Updated to receive floating/interactions props |
| Resizable.tsx | New component wrapping re-resizable library |
| Draggable.tsx | Enhanced to support asChild pattern for composition |
| event.util.ts | Added helper functions for event form opening and element selection |
| focus.util.ts | Enhanced focus logic based on cursor position |
| grid-organization.util.ts | Renamed observable for consistency |
packages/web/src/views/Day/components/Agenda/Events/TimedAgendaEvent/TimedAgendaEvent.tsx
Show resolved
Hide resolved
...b/src/views/Day/components/Agenda/Events/TimedAgendaEvent/DraggableTimedAgendaEvent.test.tsx
Outdated
Show resolved
Hide resolved
...es/web/src/views/Day/components/Agenda/Events/TimedAgendaEvent/DraggableTimedAgendaEvent.tsx
Show resolved
Hide resolved
| const events = useMemo(() => { | ||
| if (!draft || !StringV4Schema.safeParse(draft._id).success) { | ||
| return sortedAllDayEvents; | ||
| } | ||
| }, | ||
| [openEventForm], | ||
| ); | ||
|
|
||
| return ( | ||
| <Droppable | ||
| as="div" | ||
| dndProps={{ id: ID_GRID_ALLDAY_ROW }} | ||
| data-id="all-day-agendas" | ||
| id={ID_GRID_ALLDAY_ROW} | ||
| tabIndex={0} | ||
| aria-label="All-day events section" | ||
| {...(allDayEvents.length > 0 ? {} : { title: "All-day events section" })} | ||
| className={classNames( | ||
| "group flex max-h-36 min-h-8 cursor-cell flex-col gap-1 pt-2", | ||
| "overflow-x-hidden overflow-y-auto", | ||
| "border-t border-gray-400/20", | ||
| "focus-visible:rounded focus-visible:ring-2", | ||
| "focus:outline-none focus-visible:ring-yellow-200", | ||
| )} | ||
| style={{ | ||
| overscrollBehavior: "contain", | ||
| scrollbarGutter: "stable both-edges", | ||
| }} | ||
| onClick={() => openEventForm()} | ||
| onKeyDown={onEnterKey} | ||
| > | ||
| {sortedAllDayEvents.map((event) => ( | ||
| <DraggableAllDayAgendaEvent | ||
| key={event._id} | ||
| event={event as Schema_GridEvent} | ||
| /> | ||
| ))} | ||
| </Droppable> | ||
| ); | ||
| }; | ||
| const withoutDraft = sortedAllDayEvents.filter( | ||
| (event) => event._id !== draft._id, | ||
| ); | ||
|
|
||
| const allEvents = [draft, ...withoutDraft]; | ||
|
|
||
| return allEvents.sort(compareEventsByTitle); | ||
| }, [sortedAllDayEvents, draft]); |
There was a problem hiding this comment.
This useMemo has a dependency issue. The sortedAllDayEvents array is created on every render (line 28), which means this useMemo will recompute on every render, defeating its purpose. Consider moving the sorting operation inside the useMemo or making sortedAllDayEvents a separate useMemo with allDayEvents as the dependency.
Co-authored-by: Copilot <175728472+Copilot@users.noreply.github.com>
There was a problem hiding this comment.
Pull request overview
Copilot reviewed 51 out of 52 changed files in this pull request and generated 10 comments.
Comments suppressed due to low confidence (1)
packages/web/src/views/Day/util/agenda/focus.util.ts:20
- The call to
element.scrollIntoViewis made beforeelement.focus, but thenpreventScroll: trueis passed tofocus(). This order seems incorrect - you should focus first withpreventScroll: true, then scroll into view. Otherwise, the browser may scroll twice (once during focus if preventScroll fails, once during scrollIntoView).
packages/web/src/views/Day/components/Agenda/Events/AllDayAgendaEvent/AllDayAgendaEvents.tsx
Show resolved
Hide resolved
...es/web/src/views/Day/components/Agenda/Events/TimedAgendaEvent/DraggableTimedAgendaEvent.tsx
Show resolved
Hide resolved
packages/web/src/views/Day/components/Agenda/Events/TimedAgendaEvent/TimedAgendaEvents.tsx
Show resolved
Hide resolved
packages/web/src/views/Day/components/Agenda/Events/TimedAgendaEvent/TimedAgendaEvent.tsx
Show resolved
Hide resolved
packages/web/src/views/Day/components/Agenda/Events/TimedAgendaEvent/TimedAgendaEvents.tsx
Show resolved
Hide resolved
* :sparkles feat(day-view): show preview for new events - Added `useOpenAgendaEventPreview` and `useOpenEventContextMenu` hooks to manage event previews and context menus. - Created tests for both hooks to ensure correct functionality when interacting with events. - Refactored event form handling in `useOpenEventForm` to streamline event creation and editing. - Introduced `useCloseEventForm` hook to handle closing event forms and resetting drafts. - Updated `useSaveEventForm` to integrate with the new close event form logic. - Enhanced utility functions for event handling and focus management. - Removed unnecessary context providers from `DayViewContent` for cleaner component structure. - add a re-resizable package * :sparkles feat: refactor event handling and improve test setups * fix: update existing event check to return false instead of null * Update packages/web/src/components/DND/Resizable.tsx Co-authored-by: Copilot <175728472+Copilot@users.noreply.github.com> * :bug fix: ensure element scrolls into view before focusing in focusElement function --------- Co-authored-by: Copilot <175728472+Copilot@users.noreply.github.com>
* Initial plan * Refactor: Replace googleapis with @googleapis/calendar and gaxios Co-authored-by: victor-enogwe <23452630+victor-enogwe@users.noreply.github.com> * Fix GaxiosError mock objects for compatibility with gaxios library Co-authored-by: victor-enogwe <23452630+victor-enogwe@users.noreply.github.com> * Address code review: Add code property to GaxiosError instances Co-authored-by: victor-enogwe <23452630+victor-enogwe@users.noreply.github.com> * ➖ chore(dependencies): remove unused express-validator and express-winston packages (#1339) * build(deps): bump validator from 13.15.20 to 13.15.23 Bumps [validator](https://github.com/validatorjs/validator.js) from 13.15.20 to 13.15.23. - [Release notes](https://github.com/validatorjs/validator.js/releases) - [Changelog](https://github.com/validatorjs/validator.js/blob/master/CHANGELOG.md) - [Commits](validatorjs/validator.js@13.15.20...13.15.23) --- updated-dependencies: - dependency-name: validator dependency-version: 13.15.23 dependency-type: indirect ... Signed-off-by: dependabot[bot] <support@github.com> * ➖ chore(dependencies): remove unused express-validator and express-winston packages --------- Signed-off-by: dependabot[bot] <support@github.com> Co-authored-by: dependabot[bot] <49699333+dependabot[bot]@users.noreply.github.com> Co-authored-by: Tyler Dane <tyler@switchback.tech> Co-authored-by: Victor Enogwe <23452630+victor-enogwe@users.noreply.github.com> * :sparkles feat(day-view): show preview for new events (#1371) * :sparkles feat(day-view): show preview for new events - Added `useOpenAgendaEventPreview` and `useOpenEventContextMenu` hooks to manage event previews and context menus. - Created tests for both hooks to ensure correct functionality when interacting with events. - Refactored event form handling in `useOpenEventForm` to streamline event creation and editing. - Introduced `useCloseEventForm` hook to handle closing event forms and resetting drafts. - Updated `useSaveEventForm` to integrate with the new close event form logic. - Enhanced utility functions for event handling and focus management. - Removed unnecessary context providers from `DayViewContent` for cleaner component structure. - add a re-resizable package * :sparkles feat: refactor event handling and improve test setups * fix: update existing event check to return false instead of null * Update packages/web/src/components/DND/Resizable.tsx Co-authored-by: Copilot <175728472+Copilot@users.noreply.github.com> * :bug fix: ensure element scrolls into view before focusing in focusElement function --------- Co-authored-by: Copilot <175728472+Copilot@users.noreply.github.com> * docs: replace discord links in README (#1383) * Update issue template and command palette links to reflect GitHub Discussions instead of Discord. This change enhances community engagement by directing users to the appropriate platform for questions and feedback. * Update README.md to reflect new project description and community engagement links. Changed project description to emphasize its role as a minimal task manager for engineers and updated contact links to direct users to GitHub Discussions instead of Discord. * Update .github/ISSUE_TEMPLATE/config.yml Co-authored-by: Copilot <175728472+Copilot@users.noreply.github.com> * Update packages/web/src/common/constants/more.cmd.constants.ts Co-authored-by: Copilot <175728472+Copilot@users.noreply.github.com> * Update .github/ISSUE_TEMPLATE/config.yml Co-authored-by: Copilot <175728472+Copilot@users.noreply.github.com> --------- Co-authored-by: Copilot <175728472+Copilot@users.noreply.github.com> * feat: add a11y skills agent (#1387) * feat(accessibility): add Accessibility Change Audit guideline document - Introduced a new SKILL.md file outlining the Accessibility Change Audit process. - The document provides an overview, usage scenarios, a checklist for auditing UI changes, and minimal fix patterns to enhance accessibility in UI components. - Aimed at improving semantic structure, catching accessibility regressions, and increasing test reliability. * refactor(accessibility): update Accessibility Change Audit guidelines - Enhanced the description to include accessibility audits and flaky UI tests. - Clarified prerequisites and instructions for conducting audits. - Introduced a diff-first approach for evaluating UI changes. - Expanded the audit checklist and output format for better clarity and usability. * feat(accessibility): introduce new a11y-audit skills and update existing guidelines - Added new SKILL.md files for `claude-a11y-audit` and `codex-a11y-audit`, providing detailed descriptions for accessibility audits. - Updated the existing `accessibility-change-audit` SKILL.md to rename it to `a11y-audit` for consistency and clarity. - Adjusted .gitignore to exclude specific settings files. * feat(a11y): add codex-a11y-audit skill documentation - Introduced a new SKILL.md file for `codex-a11y-audit`, detailing its use for reviewing UI diffs, accessibility audits, and identifying a11y regressions. - The document includes a link to the canonical skill for consistency in accessibility auditing practices. * feat(a11y): update a11y-audit skill documentation and introduce new file - Updated the SKILL.md files for `claude-a11y-audit` and `codex-a11y-audit` to link to the new `a11y-audit` documentation. - Introduced a comprehensive SKILL.md file for `a11y-audit`, detailing its purpose, prerequisites, instructions, and a checklist for conducting accessibility audits. - Enhanced the document to provide clear guidelines for identifying accessibility regressions and proposing minimal fixes. * :sparkles feat(agenda-event resize): support resizable agenda event preview * Initial plan * Implement resizable event preview with top and bottom handles Co-authored-by: victor-enogwe <23452630+victor-enogwe@users.noreply.github.com> * Address code review feedback: improve resize logic and reduce duplication Co-authored-by: victor-enogwe <23452630+victor-enogwe@users.noreply.github.com> * :sparkles feat(agenda-event resize): support resizable agenda event preview :package deps(rxjs-state-management): introduce rxjs state @ngneat/elf library - Updated EventContextMenu and related components to utilize activeEvent$ observable for managing active events. - Replaced setDraft with resetDraft and resetActiveEvent in event form hooks to improve state management. - Refactored tests to mock new event store structure and ensure proper event handling. - Introduced utility functions for calculating event height and rounding minutes to nearest fifteen. - Updated yarn.lock to include new dependencies for @ngneat/elf-entities and @ngneat/use-observable. * :bugfix fix(resize-agenda-event): improve event handling and add tests * Update packages/web/src/common/hooks/useEventResizeActions.ts Co-authored-by: Copilot <175728472+Copilot@users.noreply.github.com> * feat(resize-agenda-event): add bounds parameter to useEventResizeActions for improved resizing logic * refactor(useEventResizeActions): remove debug log from resizing function * feat(useEventResizeActions): enhance resizing logic with bounds clamping and update tests --------- Co-authored-by: copilot-swe-agent[bot] <198982749+Copilot@users.noreply.github.com> Co-authored-by: victor-enogwe <23452630+victor-enogwe@users.noreply.github.com> Co-authored-by: Copilot <175728472+Copilot@users.noreply.github.com> * :bug fix(agenda-loading): fix AgendaSkeleton displaying on every event reload (#1390) * Initial plan * Add LoadingProgressLine component and update TimedAgendaEvents to use it Co-authored-by: victor-enogwe <23452630+victor-enogwe@users.noreply.github.com> * Add tests for LoadingProgressLine and update Agenda tests Co-authored-by: victor-enogwe <23452630+victor-enogwe@users.noreply.github.com> * Update LoadingProgressLine component comment for clarity Co-authored-by: victor-enogwe <23452630+victor-enogwe@users.noreply.github.com> * Move LoadingProgressLine inside mainGrid with absolute positioning Co-authored-by: victor-enogwe <23452630+victor-enogwe@users.noreply.github.com> * Move LoadingProgressLine to top of ID_GRID_EVENTS_TIMED (timedEvents div) Co-authored-by: victor-enogwe <23452630+victor-enogwe@users.noreply.github.com> * :bug fix(agenda-loading): make loading animation subtle * refactor(tests): remove absolute positioning test for LoadingProgressLine * feat(hooks): add useHasLoadedOnce hook for tracking initial load state refactor(agenda): integrate useHasLoadedOnce in Agenda and TimedAgendaEvents components * test(agenda): improve loading state handling and progress line rendering * test(hooks): add tests for useHasLoadedOnce hook functionality --------- Co-authored-by: copilot-swe-agent[bot] <198982749+Copilot@users.noreply.github.com> Co-authored-by: victor-enogwe <23452630+victor-enogwe@users.noreply.github.com> * :sparkles feat(agenda-events): select surface to create timed events (#1392) chore: update dev dependencies add jest-canvas-mock * :sparkles feat(agenda-events): add event shortcuts (n, m) to Day view command palette (#1389) * Initial plan * Add Create event [n] and Edit event [m] to DayCmdPalette with tests Co-authored-by: victor-enogwe <23452630+victor-enogwe@users.noreply.github.com> * Fix test mocks and pass all tests with linting Co-authored-by: victor-enogwe <23452630+victor-enogwe@users.noreply.github.com> * Remove unnecessary onEventTargetVisibility wrapper from event shortcuts Co-authored-by: victor-enogwe <23452630+victor-enogwe@users.noreply.github.com> * :bug fix(DayCmdPalette): update event handlers to use queueMicrotask to stagger open and keep focus on open --------- Co-authored-by: copilot-swe-agent[bot] <198982749+Copilot@users.noreply.github.com> Co-authored-by: victor-enogwe <23452630+victor-enogwe@users.noreply.github.com> * :sparkles feat(agenda-events): fix event form context menu visibility (#1393) * :sparkles feat(agenda-events): improve z-index mgmt within event form add event context menu delete and duplicate functionalities * fix(context-menu): do not close form if delete is not confirmed * fix(context-menu): delete draft events on confirmation * update yarn.lock * refactor(auth, user, error handling): improve error messages and handling in authentication and user services - Updated error messages in `google.auth.service.ts` to clarify authentication client initialization issues. - Enhanced error handling in `user.controller.ts` to catch and respond to `BaseError` instances appropriately. - Added logging in `error.express.handler.ts` for better debugging of errors. - Improved user profile retrieval error message in `user.service.ts` for clarity. - Adjusted user profile loading logic in `UserProvider.tsx` to prevent unnecessary re-renders. - Updated API response handling in `compass.api.ts` to redirect users to onboarding on profile not found errors. * refactor(user.controller): enhance error handling for user metadata retrieval - Wrapped user metadata fetching logic in try-catch blocks to handle potential errors. - Improved response handling for `BaseError` instances, ensuring appropriate status codes are returned. - Maintained existing functionality while increasing robustness against errors during user metadata operations. * refactor(user.service, StorageInfoModal): remove debug log and simplify text - Removed console log statement from `user.service.ts` to clean up the code. - Simplified the explanatory text in `StorageInfoModal.tsx` for better clarity and conciseness. * refactor(error.express.handler): remove debug log for cleaner error handling - Removed console log statement from `error.express.handler.ts` to streamline error handling and improve code clarity. * refactor(mock.events.init, error mocks): streamline error handling and improve mock structure - Removed unused type imports and simplified the event simulation function in `mock.events.init.ts`. - Enhanced error mock structures in `error.google.invalidGrant.ts`, `error.google.invalidValue.ts`, and `error.invalidSyncToken.ts` by using `Headers` and `URL` objects for better clarity and consistency. - Updated error handling to include more detailed response structures, improving the robustness of the mocks. * refactor(gcal.factory, google.auth.service, error.express.handler, gcal.service, gcal.utils): enhance mock responses and error handling - Introduced a `createMockGaxiosResponse` function in `gcal.factory.ts` to standardize mock responses for Google Calendar API interactions. - Updated error handling in `google.auth.service.ts` to provide more detailed GaxiosError structures. - Improved URL handling in `error.express.handler.ts` for better email extraction from error configurations. - Modified response validation in `gcal.service.ts` to accommodate new response structures. - Enhanced error checking in `gcal.utils.ts` to ensure proper handling of error codes. * chore: add return to user.controller --------- Signed-off-by: dependabot[bot] <support@github.com> Co-authored-by: copilot-swe-agent[bot] <198982749+Copilot@users.noreply.github.com> Co-authored-by: victor-enogwe <23452630+victor-enogwe@users.noreply.github.com> Co-authored-by: dependabot[bot] <49699333+dependabot[bot]@users.noreply.github.com> Co-authored-by: Copilot <175728472+Copilot@users.noreply.github.com>
What does this PR do?
This PR adds suuport for showing new event previews.
useOpenAgendaEventPreviewanduseOpenEventContextMenuhooks to manage event previews and context menus.useOpenEventFormto support event previews.useCloseEventFormhook to handle closing event forms and resetting drafts.useSaveEventFormto integrate with the new close event form logic.DayViewContentfor cleaner component structure.Use Case
closes #1363
fixes and closes #1365